package order

import (
	"context"
	"time"

	"gitee.com/wenchangshou/simple-admin-pancakebot-rpc/ent"
	"gitee.com/wenchangshou/simple-admin-pancakebot-rpc/ent/pancakebotorder"
	"gitee.com/wenchangshou/simple-admin-pancakebot-rpc/internal/svc"
	"gitee.com/wenchangshou/simple-admin-pancakebot-rpc/types/pancakebot"
	"github.com/suyuan32/simple-admin-common/enum/common"
	"github.com/suyuan32/simple-admin-common/i18n"

	"github.com/zeromicro/go-zero/core/logx"
)

type UpdatePancakebotOrderLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewUpdatePancakebotOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdatePancakebotOrderLogic {
	return &UpdatePancakebotOrderLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *UpdatePancakebotOrderLogic) UpdatePancakebotOrder(in *pancakebot.PancakebotOrderInfo) (*pancakebot.BaseResp, error) {
	// 查询订单是否存在
	_, err := l.svcCtx.DB.PancakebotOrder.Query().
		Where(pancakebotorder.IDEQ(*in.Id)).
		Only(l.ctx)
	if err != nil {
		return nil, err
	}

	// 构建更新查询
	updateQuery := l.svcCtx.DB.PancakebotOrder.UpdateOneID(*in.Id)

	// 更新出餐口编号
	if in.OutletNo != nil {
		outletNo := int(*in.OutletNo)
		updateQuery = updateQuery.SetNillableOutletNo(&outletNo)
	}

	// 更新出餐时间
	if in.OutletTime != nil {
		outletTime := time.UnixMilli(*in.OutletTime)
		updateQuery = updateQuery.SetNillableOutletTime(&outletTime)
	}

	// 更新支付状态
	if in.PayStatus != nil {
		updateQuery = updateQuery.SetPayStatus(*in.PayStatus)
	}

	// 更新支付订单ID
	if in.PayOrderId != nil {
		updateQuery = updateQuery.SetNillablePayOrderId(in.PayOrderId)
	}

	// 更新支付时间
	if in.PayTime != nil {
		payTime := time.UnixMilli(*in.PayTime)
		updateQuery = updateQuery.SetNillablePayTime(&payTime)
	}

	// 更新支付渠道
	if in.PayChannelCode != nil {
		updateQuery = updateQuery.SetNillablePayChannelCode(in.PayChannelCode)
	}

	// 更新退款ID
	if in.PayRefundId != nil {
		updateQuery = updateQuery.SetNillablePayRefundID(in.PayRefundId)
	}

	// 更新退款金额
	if in.RefundPrice != nil {
		updateQuery = updateQuery.SetNillableRefundPrice(in.RefundPrice)
	}

	// 更新退款时间
	if in.RefundTime != nil {
		refundTime := time.UnixMilli(*in.RefundTime)
		updateQuery = updateQuery.SetNillableRefundTime(&refundTime)
	}
	if in.OrderStatus != nil {
		updateQuery = updateQuery.SetOrderStatus(int64(*in.OrderStatus))
	}
	// 如果当前订单状态更新为待取餐，则执行相关逻辑
	if in.OrderStatus != nil && *in.OrderStatus == uint64(common.OrderStatusToPickup) {
		outletTime := time.Now()
		updateQuery = updateQuery.SetNillableOutletTime(&outletTime)
	}

	// 执行更新
	err = updateQuery.Exec(l.ctx)
	if err != nil {
		return nil, err
	}

	if in.OrderStatus == nil || *in.OrderStatus != uint64(common.OrderStatusCompleted) {
		return &pancakebot.BaseResp{Msg: i18n.UpdateSuccess}, nil
	}

	// 查询支付时间最早的一个待制作订单
	waitMakeOrder, err := l.svcCtx.DB.PancakebotOrder.Query().
		Where(pancakebotorder.OrderStatusEQ(int64(common.OrderStatusPaid))).
		Order(pancakebotorder.ByPayTime()).
		First(l.ctx)

	// 如果订单状态更新为已完成，并且没有待制作订单，则释放出餐口
	if err != nil && ent.IsNotFound(err) {
		if in.OrderStatus != nil && *in.OrderStatus == uint64(common.OrderStatusCompleted) {
			err = l.releaseOutletPort(*in.Id)
			if err != nil {
				l.Logger.Errorf("释放出餐口失败: %v", err)
				return nil, err
			}
		}
	}
	err = l.svcCtx.DB.PancakebotOrder.UpdateOneID(waitMakeOrder.ID).
		SetNillableOutletNo(waitMakeOrder.OutletNo).
		SetOrderStatus(int64(common.OrderStatusToMake)).
		Exec(l.ctx)
	if err != nil {
		l.Logger.Errorf("更新待制作订单失败: %v", err)
		return nil, err
	}
	return &pancakebot.BaseResp{Msg: i18n.UpdateSuccess}, nil
}

// releaseOutletPort 释放设备的出餐口
func (l *UpdatePancakebotOrderLogic) releaseOutletPort(id uint64) error {

	var deviceID uint64
	var outletNo int
	// 重新查询订单获取完整信息
	order, err := l.svcCtx.DB.PancakebotOrder.Get(l.ctx, id)
	if err != nil {
		l.Logger.Errorf("查询订单失败: %v", err)
		return err
	} else if order.OutletNo != nil {
		// 释放出餐口
		deviceID = order.DeviceID
		outletNo = *order.OutletNo
	}
	// 查询设备
	device, err := l.svcCtx.DB.Device.Get(l.ctx, deviceID)
	if err != nil {
		return err
	}

	// 检查出餐口列表
	if len(device.OutletPorts) == 0 {
		return nil // 没有出餐口，直接返回
	}

	// 更新出餐口状态
	updated := false
	for i, port := range device.OutletPorts {
		if port.Number == outletNo {
			// 找到对应的出餐口，设置为未使用状态
			device.OutletPorts[i].InUse = false
			device.OutletPorts[i].Status = 0 // 0: 空闲
			updated = true
			break
		}
	}

	// 如果找到并更新了出餐口，保存到数据库
	if updated {
		err = l.svcCtx.DB.Device.UpdateOneID(deviceID).
			SetOutletPorts(device.OutletPorts).
			Exec(l.ctx)
		if err != nil {
			return err
		}
	}

	return nil
}
